package com.tiancheng.trade.merchant.util;

import com.tiancheng.trade.merchant.vo.CellMergeVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.WorkbookUtil;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.Assert;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelUtil {

    public static Workbook buildWorkbook(String sheetName, String[] title, List<Map<String, Object>> dataList) {

        return buildWorkbook((workbook) -> {
            Sheet sheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(sheetName));

            int firstRowIndex = 0;
            int cellIndex = 0;
            if (title != null) {
                Row firstRow = sheet.createRow(firstRowIndex);
                for (String str : title) {
                    firstRow.createCell(cellIndex).setCellValue(str);
                    cellIndex++;
                }
            }
            if (dataList == null) {
                return;
            }
            int rowIndex = firstRowIndex;
            for (Map<String, Object> dataRow : dataList) {
                rowIndex++;
                Row row = sheet.createRow(rowIndex);
                cellIndex = 0;
                for (Map.Entry<String, Object> dataCell : dataRow.entrySet()) {
                    Object cell = dataCell.getValue();
                    String v = cell == null ? "" : cell.toString();
                    row.createCell(cellIndex).setCellValue(v);
                    cellIndex++;
                }
            }
            try {
                autoSizeColumn(sheet, cellIndex);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 设置自适应宽度
     *
     * @param sheet     {@link Sheet}
     * @param maxColumn {@link Integer}
     **/
    private static void autoSizeColumn(Sheet sheet, Integer maxColumn) throws Exception {
        // 列宽自适应，只对英文和数字有效
        for (int i = 0; i <= maxColumn; i++) {
            sheet.autoSizeColumn(i);
        }
        // 获取当前列的宽度，然后对比本列的长度，取最大值
        for (int columnNum = 0; columnNum <= maxColumn; columnNum++) {
            int columnWidth = sheet.getColumnWidth(columnNum) / 256;
            for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
                Row currentRow;
                // 当前行未被使用过
                if (sheet.getRow(rowNum) == null) {
                    currentRow = sheet.createRow(rowNum);
                } else {
                    currentRow = sheet.getRow(rowNum);
                }

                if (currentRow.getCell(columnNum) != null) {
                    Cell currentCell = currentRow.getCell(columnNum);
                    int length = currentCell.toString().getBytes("GBK").length;
                    if (columnWidth < length + 1) {
                        columnWidth = length + 1;
                    }
                }
            }
            int width = columnWidth * 256;
            if (width < 255 * 256) {
                sheet.setColumnWidth(columnNum, width);
            } else {
                sheet.setColumnWidth(columnNum, 255 * 256 - 1);
            }
        }
    }

    /**
     * 导出Excel并支持标题合并
     *
     * @param sheetName     表名
     * @param title1        需要合并的标题
     * @param title2        数据列表标题
     * @param dataList      数据
     * @param cellMergeList 合并规则
     * @return {@link Workbook}
     */
    public static Workbook buildWorkbook2(String sheetName, HashMap<Integer, String> title1, String[] title2,
                                          List<Map<String, Object>> dataList, List<CellMergeVO> cellMergeList) {

        return buildWorkbook((workbook) -> {
            String safeSheetName = WorkbookUtil.createSafeSheetName(sheetName);
            Sheet sheet = workbook.createSheet(safeSheetName);
            XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
            style.setAlignment(HorizontalAlignment.CENTER);
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            int firstRowIndex = 0;
            // 需要合并的标题
            if (title1 != null) {
                Row firstRow = sheet.createRow(firstRowIndex);
                for (Integer key : title1.keySet()) {
                    if (title1.get(key) != null) {
                        Cell cell = firstRow.createCell(key);
                        cell.setCellValue(title1.get(key));
                        cell.setCellStyle(style);
                    }
                }
            }
            firstRowIndex = 1;
            int cellIndex = 0;
            // 数据标题
            if (title2 != null) {

                Row firstRow = sheet.createRow(firstRowIndex);
                for (String str : title2) {
                    Cell cell = firstRow.createCell(cellIndex);
                    cell.setCellValue(str);
                    cell.setCellStyle(style);
                    cellIndex++;
                }
            }
            if (dataList == null) {
                return;
            }
            // 需要合并的列
            if (cellMergeList != null && !cellMergeList.isEmpty()) {
                for (CellMergeVO vo : cellMergeList) {
                    CellRangeAddress region = new CellRangeAddress(vo.getStartRow(), vo.getEndRow(), vo.getStartCol(), vo.getEndCol());
                    sheet.addMergedRegion(region);
                }
            }
            int rowIndex = firstRowIndex;
            for (Map<String, Object> dataRow : dataList) {
                rowIndex++;
                Row row = sheet.createRow(rowIndex);
                cellIndex = 0;
                for (Map.Entry<String, Object> dataCell : dataRow.entrySet()) {
                    Object cell = dataCell.getValue();
                    String v = cell == null ? "" : cell.toString();
                    row.createCell(cellIndex).setCellValue(v);
                    cellIndex++;
                }
            }

            try {
                autoSizeColumn(sheet, cellIndex);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    public static Workbook buildWorkbook(SheetHandler handler) {
        Assert.notNull(handler, "handler不能为空");
        Workbook workbook = new XSSFWorkbook();
        handler.process(workbook);
        return workbook;
    }

    public static void exportExcle(HttpServletRequest request, HttpServletResponse response, Workbook workbook, String fileName)
            throws IOException {

        // 解决不同浏览器中文乱码问题
        String userAgent = request.getHeaders("User-Agent").nextElement().toLowerCase();
        if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
            fileName = URLEncoder.encode(fileName, "UTF-8");
        } else {
            fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        }
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
        response.setContentType("application/force-download");
        workbook.write(response.getOutputStream());
    }


}
